﻿using System;

namespace YArchitech.Plumbing
{
	public class GaussMatrix
	{
		public GaussMatrix()
		{
			this.InitMatrix();
		}

		public void InitMatrix()
		{
			for (int i = 0; i < this.m_dResult.Length; i++)
			{
				this.m_dResult[i] = 0.0;
			}
			for (int j = this.m_Ab.GetLowerBound(0); j < this.m_Ab.GetUpperBound(0); j++)
			{
				for (int k = this.m_Ab.GetLowerBound(1); k < this.m_Ab.GetUpperBound(1); k++)
				{
					this.m_Ab[j, k] = 0.0;
				}
			}
		}

		protected void Changeline(int r, int k, int nDs)
		{
			for (int i = 1; i <= nDs + 1; i++)
			{
				this.m_Ab[0, i] = this.m_Ab[r, i];
			}
			for (int i = 1; i <= nDs + 1; i++)
			{
				this.m_Ab[r, i] = this.m_Ab[k, i];
			}
			for (int i = 1; i <= nDs + 1; i++)
			{
				this.m_Ab[k, i] = this.m_Ab[0, i];
			}
		}

		protected double Findmax(int m, int nDs, ref int findK)
		{
			double num = 0.0;
			for (int i = m; i <= nDs; i++)
			{
				if (Math.Abs(this.m_Ab[i, m]) > num)
				{
					num = Math.Abs(this.m_Ab[i, m]);
					findK = i;
				}
			}
			return num;
		}

		public bool GaussMatrixCal(int nDs)
		{
			for (int i = 1; i <= nDs - 1; i++)
			{
				int num = 0;
				if (this.Findmax(i, nDs, ref num) == 0.0)
				{
					return false;
				}
				if (num != i)
				{
					this.Changeline(num, i, nDs);
				}
				for (int j = i + 1; j <= nDs; j++)
				{
					for (int k = i + 1; k <= nDs + 1; k++)
					{
						this.m_Ab[j, k] = this.m_Ab[j, k] - this.m_Ab[i, k] * this.m_Ab[j, i] / this.m_Ab[i, i];
					}
				}
			}
			this.m_dResult[nDs - 1] = this.m_Ab[nDs, nDs + 1] / this.m_Ab[nDs, nDs];
			for (int l = nDs - 1; l >= 1; l--)
			{
				double num2 = 0.0;
				for (int m = l + 1; m <= nDs; m++)
				{
					num2 += this.m_Ab[l, m] * this.m_dResult[m - 1];
				}
				this.m_dResult[l - 1] = (this.m_Ab[l, nDs + 1] - num2) / this.m_Ab[l, l];
			}
			return true;
		}

		private const int Max_Number = 10;

		private const int Max_Params = 5;

		public double[,] m_Ab = new double[10, 11];

		public double[] m_dResult = new double[10];
	}
}
